home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / cuj9205.zip / 1005016B < prev    next >
Text File  |  1992-06-02  |  2KB  |  106 lines

  1.  
  2. Listing 4 -- xstod.c
  3.  
  4.  
  5. /* _Stod function */
  6. #include <ctype.h>
  7. #include <float.h>
  8. #include <limits.h>
  9. #include <locale.h>
  10. #include <stdlib.h>
  11. #include "xmath.h"
  12.  
  13. #define SIG_MAX    32
  14.  
  15. double _Stod(const char *s, char **endptr)
  16.     {    /* convert string to double, with checking */
  17.     const char point = localeconv()->decimal_point[0];
  18.     const char *sc;
  19.     char buf[SIG_MAX], sign;
  20.     double x;
  21.     int ndigit, nsig, nzero, olead, opoint;
  22.  
  23.     for (sc = s; isspace(*sc); ++sc)
  24.         ;
  25.     sign = *sc == '-' || *sc == '+' ? *sc++ : '+';
  26.     olead = -1, opoint = -1;
  27.     for (ndigit = 0, nsig = 0, nzero = 0; ; ++sc)
  28.         if (*sc == point)
  29.             if (0 <= opoint)
  30.                 break;    /* already seen point */
  31.             else
  32.                 opoint = ndigit;
  33.         else if (*sc == '0')
  34.             ++nzero, ++ndigit;
  35.         else if (!isdigit(*sc))
  36.             break;
  37.         else
  38.             {    /* got a nonzero digit */
  39.             if (olead < 0)
  40.                 olead = nzero;
  41.             else    /* deliver zeros */
  42.                 for (; 0 < nzero && nsig < SIG_MAX; --nzero)
  43.                     buf[nsig++] = 0;
  44.             ++ndigit;
  45.             if (nsig < SIG_MAX)    /* deliver digit */
  46.                 buf[nsig++] = *sc - '0';
  47.             }
  48.     if (ndigit == 0)
  49.         {    /* set endptr */
  50.         if (endptr)
  51.             *endptr = (char *)s;
  52.         return (0.0);
  53.         }
  54.     for (; 0 < nsig && buf[nsig - 1] == 0; --nsig)
  55.         ;    /* skip trailing digits */
  56.      {    /* compute significand */
  57.     const char *pc = buf;
  58.     int n;
  59.     long lo[SIG_MAX/8+1];
  60.     long *pl = &lo[nsig >> 3];
  61.     static double fac[] = {0, 1e8, 1e16, 1e24, 1e32};
  62.  
  63.     for (*pl = 0, n = nsig; 0 < n; --n)
  64.         if ((n & 07) == 0)    /* start new sum */
  65.             *--pl = *pc++;
  66.         else
  67.             *pl = *pl * 10 + *pc++;
  68.     for (x = (double)lo[0], n = 0; ++n <= (nsig >> 3); )
  69.         if (lo[n] != 0)
  70.             x += fac[n] * (double)lo[n];
  71.      }
  72.      {    /* fold in any explicit exponent */
  73.     long lexp = 0;
  74.     short sexp;
  75.  
  76.     if (*sc == 'e' || *sc == 'E')
  77.         {    /* parse exponent */
  78.         const char *scsav = sc;
  79.         const char esign = *++sc == '+' || *sc == '-'
  80.             ? *sc++ : '+';
  81.  
  82.         if (!isdigit(*sc))
  83.             sc = scsav;    /* ill-formed exponent */
  84.         else
  85.             {    /* exponent looks valid */
  86.             for (; isdigit(*sc); ++sc)
  87.                 if (lexp < 100000)    /* else overflow */
  88.                     lexp = lexp * 10 + *sc - '0';
  89.             if (esign == '-')
  90.                 lexp = -lexp;
  91.             }
  92.         }
  93.     if (endptr)
  94.         *endptr = (char *)sc;
  95.     if (opoint < 0)
  96.         lexp += ndigit - nsig;
  97.     else
  98.         lexp += opoint - olead - nsig;
  99.     sexp = lexp < SHRT_MIN ? SHRT_MIN : lexp < SHRT_MAX
  100.         ? (short)lexp : SHRT_MAX;
  101.     x = _Dtento(x, sexp);
  102.     return (sign == '-' ? -x : x);
  103.      }
  104.     }
  105.  
  106.